package com.educhains.web.ctrl.frontend;

import com.alibaba.fastjson.JSONObject;
import com.educhains.module.message.service.EmailService;
import com.educhains.module.user.service.UserService;
import com.educhains.module.user.vo.User;
import com.educhains.web.util.*;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.util.Date;

@Controller
public class IndexCtrl {

    @Autowired
    private UserService userService = null;

    @Autowired
    private EmailService emailService = null;

    private static final String LOGIN_CAPTCHA = "loginCaptcha";

    private static final String REGISTER_CAPTCHA = "registerCaptcha";

    private static final int AUTO_LOGIN_TIME_OUT = 60 * 60 * 24 * 7;

    /**
     * Index
     *
     * @return
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index() {
        return "frontend/index/index";
    }

    /**
     * Login page
     *
     * @return
     */
    @RequestMapping(value = "/loginPage")
    public String loginPage(HttpServletRequest request) {
        request.setAttribute("entrance", "loginPage");
        return "frontend/index/loginAndRegister";
    }

    /**
     * Register page
     *
     * @return
     */
    @RequestMapping(value = "/registerPage")
    public String registerPage(HttpServletRequest request) {
        request.setAttribute("entrance", "registerPage");
        return "frontend/index/loginAndRegister";
    }

    /**
     * Activate Email
     *
     * @param request
     * @return
     */
    @RequestMapping("/activateEmail")
    public String activateEmail(HttpServletRequest request) {
        String token = request.getParameter("token");
        String email = request.getParameter("email");
        boolean check = emailService.checkActivateEmail(token, email);
        if (check) {
            User dbUser = userService.getUserByEmail(email);
            dbUser.setUserAuthority(User.USER_AUTHORITY_ACTIVE);
            userService.updateUserAuthority(dbUser);
            request.setAttribute("activateResult", true);
        } else {
            request.setAttribute("activateResult", false);
        }
        return "/frontend/index/activatePage";
    }

    /**
     * Register
     *
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/register", produces = "application/json; charset=utf-8", method = RequestMethod.POST)
    public String register(HttpServletRequest request) throws Exception {
        String userName = request.getParameter("userName");
        String userEmail = request.getParameter("userEmail");
        String userPassword = request.getParameter("userPassword");
        String requestCaptcha = request.getParameter("imgCaptcha");
        String sessionCaptcha = SessionUtils.getAttribute(request, REGISTER_CAPTCHA, String.class);
        if (StringUtils.isEmpty(userEmail) || StringUtils.isEmpty(userPassword)) {
            return returnBody(false, "请输入账号密码");
        }
        if (!StringUtils.isEmail(userEmail)) {
            return returnBody(false, "请输入正确的邮箱地址");
        }
//        if (StringUtils.isEmpty(requestCaptcha)) {
//            return returnBody(false, "请输入验证码");
//        }
//        if (requestCaptcha.compareToIgnoreCase(sessionCaptcha) != 0) {
//            return returnBody(false, "请输入正确的验证码");
//        }
        //FIXME more validation
        User dbUser = userService.getUserByEmail(userEmail);
        if (dbUser != null && dbUser.getUserAuthority() == User.USER_AUTHORITY_APPLYING) {
            boolean result = emailService.sendActivateEmail(WebUtils.getRequestPath(request, ""), userEmail);
            //FIXME will redirect
            if (result) {
                return returnBody(result, "账号已存在，已重新发送激活邮件");
            } else {
                return returnBody(result, "请查收您的激活邮件");
            }
        }
        if (dbUser != null) {
            return returnBody(false, "账号已存在");
        }
        User registerUser = new User();
        Date now = new Date();
        String salt = StringUtils.generateRandomString(16);
        registerUser.setUserEmail(userEmail);
        registerUser.setUserSalt(salt);
        registerUser.setUserPwd(CipherUtils.generatePassword(userPassword + salt));
        registerUser.setUserName(userName);
        registerUser.setUserContactInfo("");
        registerUser.setUserAuthority(User.USER_AUTHORITY_APPLYING);
        registerUser.setUserIsBan(false);
        registerUser.setUserCreateTime(now);
        registerUser.setUserModifyTime(now);
        registerUser.setUserId(StringUtils.generateUUID());
        registerUser.setUserModifyId(registerUser.getUserId());
        registerUser.setUserContribution(0L);
        registerUser.setUserLikeNum(0);
        registerUser.setUserFunsNum(0);
        registerUser.setUserPhoto("／images/avatar/default-avatar.png");
        userService.addUser(registerUser);
        emailService.sendActivateEmail(WebUtils.getRequestPath(request, ""), userEmail);
        return returnBody(true, "注册成功");
    }

    /**
     * Login
     *
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/login", produces = "application/json; charset=utf-8", method = RequestMethod.POST)
    public String login(HttpServletRequest request, HttpServletResponse response) {
        String userEmail = request.getParameter("userEmail");
        String userPassword = request.getParameter("userPassword");
        String requestCaptcha = request.getParameter("imgCaptcha");
        String sessionCaptcha = SessionUtils.getAttribute(request, LOGIN_CAPTCHA, String.class);
        if (StringUtils.isEmpty(userEmail) || StringUtils.isEmpty(userPassword)) {
            return returnBody(false, "请输入账号密码");
        }
        if (!StringUtils.isEmail(userEmail)) {
            return returnBody(false, "请输入正确的邮箱地址");
        }
//        if (StringUtils.isEmpty(requestCaptcha)) {
//            return returnBody(false, "请输入验证码");
//        }
//        if (requestCaptcha.compareToIgnoreCase(sessionCaptcha) != 0) {
//            return returnBody(false, "请输入正确的验证码");
//        }
        //FIXME more validation
        User dbUser = userService.getUserByEmail(userEmail);
        if (dbUser == null) {
            return returnBody(false, "请输入正确的账号密码");
        }
        if (userService.login(userEmail, userPassword, dbUser.getUserSalt())) {
            SessionUtils.setUser(request, dbUser);
            String autoLogin = request.getParameter("autoLogin");
            if (StringUtils.isNotEmpty(autoLogin) && autoLogin.compareTo("true") == 0) {
                //FIXME encrypt cookie
                Cookie userEmailCookie = new Cookie(User.USER_EMAIL_COOKIE_KEY, dbUser.getUserEmail());
                Cookie passwordCookie = new Cookie(User.USER_PASSWORD_COOKIE_KEY, dbUser.getUserPwd());
                userEmailCookie.setMaxAge(AUTO_LOGIN_TIME_OUT);
                userEmailCookie.setPath("/");
                passwordCookie.setMaxAge(AUTO_LOGIN_TIME_OUT);
                passwordCookie.setPath("/");
                response.addCookie(userEmailCookie);
                response.addCookie(passwordCookie);
            }
            return returnBody(true, WebUtils.getRequestPath(request, "/"));
        } else {
            return returnBody(false, "请输入正确的账号密码");
        }
    }

    /**
     * Reset password
     *
     * @param request
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/sendResetPasswordEmail", produces = "application/json; charset=utf-8", method = RequestMethod.POST)
    public String sendResetPasswordEmail(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String userEmail = request.getParameter("userEmail");
        String userPassword = request.getParameter("userPassword");
        //FIXME need a new salt
        //String salt = StringUtils.generateRandomString(16);
        if (StringUtils.isEmpty(userEmail) || StringUtils.isEmpty(userPassword)) {
            return returnBody(false, "请输入账号密码");
        }
        if (!StringUtils.isEmail(userEmail)) {
            return returnBody(false, "请输入正确的邮箱地址");
        }
        User dbUser = userService.getUserByEmail(userEmail);
        if (dbUser == null) {
            return returnBody(false, "请输入正确的账号密码");
        }
        boolean result = emailService.sendResetPasswordEmail(WebUtils.getRequestPath(request, ""), userEmail, CipherUtils.generatePassword(userPassword + dbUser.getUserSalt()));
        return returnBody(result, "");
    }

    /**
     * Reset password Email
     *
     * @param request
     * @return
     */
    @RequestMapping("/resetPasswordEmail")
    public String resetPasswordEmail(HttpServletRequest request) {
        String email = request.getParameter("email");
        String password = request.getParameter("password");
        String token = request.getParameter("token");
        User dbUser = userService.getUserByEmail(email);
        if (dbUser == null) {
            //return returnBody(false, "请输入账号密码");
            request.setAttribute("resetResult", false);
        }
        boolean check = emailService.checkResetPasswordEmail(token, email);
        if (check) {
            dbUser.setUserPwd(password);
            userService.updateUserPassword(dbUser);
            request.setAttribute("resetResult", true);
        } else {
            request.setAttribute("resetResult", false);
        }
        return "/frontend/index/resetPasswordPage";
    }

    /**
     * Download file
     *
     * @param request
     * @param response
     */
    @RequestMapping("/download")
    public ResponseEntity<byte[]> downloadRecruitInformation(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //处理显示中文文件名的问题
        String path = request.getParameter("path");
        path = PropertyUtils.getProperty("file.index") + path;
        File file = new File(path);
        String fileName = new String(file.getName().getBytes("utf-8"), "ISO-8859-1");
        //设置请求头内容,告诉浏览器代开下载窗口
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", fileName);
        /*前端弹出下载*/
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),
                headers, HttpStatus.CREATED);
    }

    /**
     * Register captcha
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/registerCaptcha")
    public void registerCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        imageCaptcha(REGISTER_CAPTCHA, request, response);
    }


    /**
     * Login captcha
     *
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/loginCaptcha")
    public void loginCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
        imageCaptcha(LOGIN_CAPTCHA, request, response);
    }

    /**
     * Logout
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/logout")
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        //Delete cookie
        User user = SessionUtils.getUser(request);
        Cookie userMobileCookie = new Cookie(User.USER_EMAIL_COOKIE_KEY, user.getUserEmail());
        Cookie userPasswordCookie = new Cookie(User.USER_PASSWORD_COOKIE_KEY, user.getUserPwd());
        userMobileCookie.setMaxAge(0);
        userMobileCookie.setPath("/");
        userPasswordCookie.setMaxAge(0);
        userPasswordCookie.setPath("/");
        response.addCookie(userMobileCookie);
        response.addCookie(userPasswordCookie);
        //Invalidate session
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();
        }
        return "redirect:/";
    }

    private static String returnBody(boolean success, String msg) {
        JSONObject json = new JSONObject();
        if (success) {
            json.put("success", true);
            json.put("msg", msg);
        } else {
            json.put("success", false);
            json.put("msg", msg);
        }
        return JsonUtils.toJSONString(json);
    }

    private void imageCaptcha(String key, HttpServletRequest request, HttpServletResponse response) throws IOException {
        boolean refresh = "true".equals(request.getParameter("refresh"));
        String randomCode = null;
        if (!refresh) {
            randomCode = SessionUtils.getAttribute(request, key, String.class);
        }
        if (randomCode == null) {
            randomCode = ImageCaptchaUtils.generateVerifyCode(4);
            SessionUtils.setAttribute(request, key, randomCode);
        }
        //FIXME ImageCaptchaUtils' font and color should be changed
        ImageCaptchaUtils.outputImage(150, 40, 5, randomCode, response.getOutputStream());
    }
}
